<template>
  <view
    class="goods-sku-popup popup"
    catchtouchmove="true"
    :class="value && complete ? 'show' : 'none'"
    @touchmove.stop.prevent="moveHandle"
  >
    <!-- 页面内容开始 -->
    <view class="mask" @click="close('mask')"></view>
    <!-- 页面开始 -->
    <view
      class="layer attr-content"
      :style="
        'border-radius: ' + borderRadius + 'rpx ' + borderRadius + 'rpx 0 0;'
      "
    >
      <view class="specification-wrapper">
        <scroll-view class="specification-wrapper-content" scroll-y="true">
          <view class="specification-header">
            <view class="specification-left">
              <image
                class="product-img"
                :src="
                  selectShop.image
                    ? selectShop.image
                    : goodsInfo[goodsThumbName]
                "
                mode="aspectFill"
              ></image>
            </view>
            <view class="specification-right">
              <view
                class="price-content"
                :style="'color: ' + priceColor + ' ;'"
              >
                <text class="sign">¥</text>
                <text class="price">{{
                  (selectShop.price || defaultPrice) | priceFilter
                }}</text>
              </view>
              <view class="inventory"
                >{{ stockText }}：{{
                  selectShop[stockName] || defaultStock
                }}</view
              >
              <view
                class="choose"
                v-show="
                  goodsInfo[specListName] &&
                  goodsInfo[specListName][0].name !== defaultSingleSkuName
                "
              >
                <text v-if="!selectArr.every((val) => val == '')"
                  >已选：{{ selectArr.join(" ") }}</text
                >
              </view>
            </view>
          </view>

          <view class="specification-content">
            <view
              v-show="goodsInfo[specListName][0].name !== defaultSingleSkuName"
              class="specification-item"
              v-for="(item, index1) in goodsInfo[specListName]"
              :key="index1"
            >
              <view class="item-title">{{ item.name }}</view>
              <view class="item-wrapper">
                <view
                  class="item-content"
                  @tap="skuClick(item_value, index1, $event, index2)"
                  v-for="(item_value, index2) in item.list"
                  :key="index2"
                  :class="[
                    item_value.ishow ? '' : 'noactived',
                    subIndex[index1] == index2 ? 'actived' : '',
                  ]"
                  :style="[
                    item_value.ishow ? '' : disableStyle,
                    item_value.ishow ? btnStyle : '',
                    subIndex[index1] == index2 ? activedStyle : '',
                  ]"
                >
                  {{ item_value.name }}
                </view>
              </view>
            </view>
            <view style="display: flex">
              <view style="flex: 1">
                <text style="font-size: 26rpx; color: #333; line-height: 50rpx"
                  >数量</text
                >
              </view>
              <view style="flex: 4; text-align: right">
                <number-box
                  :min="minBuyNum"
                  :max="maxBuyNum"
                  :step="stepBuyNum"
                  v-model="selectNum"
                  :positive-integer="true"
                >
                </number-box>
              </view>
            </view>
          </view>
        </scroll-view>
        <view class="close" @click="close('close')" v-if="showClose">
          <image class="close-item" :src="closeImage"></image>
        </view>
      </view>
      <view class="btn-option">
        <view class="btn-wrapper" v-if="outFoStock || mode == 4">
          <view
            class="sure"
            style="color: #ffffff; background-color: #cccccc"
            >{{ noStockText }}</view
          >
        </view>
        <view class="btn-wrapper" v-else-if="mode == 1">
          <view
            class="sure add-cart"
            style="border-radius: 38rpx 0rpx 0rpx 38rpx"
            @click="addCart"
            :style="
              'color:' + addCartColor + ';background:' + addCartBackgroundColor
            "
            >{{ addCartText }}</view
          >
          <view
            class="sure"
            style="border-radius: 0rpx 38rpx 38rpx 0rpx"
            @click="buyNow"
            :style="
              'color:' +
              buyNowColor +
              ';background-color:' +
              buyNowBackgroundColor
            "
            >{{ buyNowText }}</view
          >
        </view>
        <view class="btn-wrapper" v-else-if="mode == 2">
          <view
            class="sure add-cart"
            @click="addCart"
            :style="
              'color:' + addCartColor + ';background:' + addCartBackgroundColor
            "
            >{{ addCartText }}</view
          >
        </view>
        <view class="btn-wrapper" v-else-if="mode == 3">
          <view
            class="sure"
            @click="buyNow"
            :style="
              'color:' + buyNowColor + ';background:' + buyNowBackgroundColor
            "
            >{{ buyNowText }}</view
          >
        </view>
      </view>
      <!-- 页面结束 -->
    </view>
    <!-- 页面内容结束 -->
  </view>
</template>

<script>
import NumberBox from "./number-box";

var that; // 当前页面对象
var vk; // 自定义函数集
export default {
  name: "GoodsSkuPopup",
  components: {
    NumberBox,
  },
  props: {
    // true 组件显示 false 组件隐藏
    value: {
      Type: Boolean,
      default: false,
    },
    // vk云函数路由模式参数开始-----------------------------------------------------------
    // 商品id
    goodsId: {
      Type: String,
      default: "",
    },
    // vk路由模式框架下的云函数地址
    action: {
      Type: String,
      default: "",
    },
    // vk云函数路由模式参数结束-----------------------------------------------------------
    // 该商品已抢完时的按钮文字
    noStockText: {
      Type: String,
      default: "该商品已抢完",
    },
    // 库存文字
    stockText: {
      Type: String,
      default: "库存",
    },
    // 商品表id的字段名
    goodsIdName: {
      Type: String,
      default: "_id",
    },
    // sku表id的字段名
    skuIdName: {
      Type: String,
      default: "_id",
    },
    // sku_list的字段名
    skuListName: {
      Type: String,
      default: "sku_list",
    },
    // spec_list的字段名
    specListName: {
      Type: String,
      default: "spec_list",
    },
    // stock的字段名
    stockName: {
      Type: String,
      default: "stock",
    },
    // sku_name的字段名
    skuName: {
      Type: String,
      default: "sku_name",
    },
    // sku组合路径的字段名
    skuArrName: {
      Type: String,
      default: "sku_name_arr",
    },
    // 默认单规格时的规格组名称
    defaultSingleSkuName: {
      Type: String,
      default: "默认",
    },
    // 模式 1:都显示  2:只显示购物车 3:只显示立即购买 4:显示缺货按钮 默认 1
    mode: {
      Type: Number,
      default: 1,
    },
    // 点击遮罩是否关闭组件 true 关闭 false 不关闭 默认true
    maskCloseAble: {
      Type: Boolean,
      default: true,
    },
    // 顶部圆角值
    borderRadius: {
      Type: [String, Number],
      default: 0,
    },
    // 商品缩略图字段名(未选择sku时)
    goodsThumbName: {
      Type: [String],
      default: "goods_thumb",
    },
    // 最小购买数量
    minBuyNum: {
      Type: Number,
      default: 1,
    },
    // 最大购买数量
    maxBuyNum: {
      Type: Number,
      default: 100000,
    },
    // 每次点击后的数量
    stepBuyNum: {
      Type: Number,
      default: 1,
    },
    // 自定义获取商品信息的函数
    customAction: {
      Type: [Function],
      default: null,
    },
    // 价格的字体颜色
    priceColor: {
      Type: String,
      default: "#fe560a",
    },
    // 立即购买按钮的文字
    buyNowText: {
      Type: String,
      default: "立即购买",
    },
    // 立即购买按钮的字体颜色
    buyNowColor: {
      Type: String,
      default: "#ffffff",
    },
    // 立即购买按钮的背景颜色
    buyNowBackgroundColor: {
      Type: String,
      default: "linear-gradient(to right, $fuint-theme, $fuint-theme)",
    },
    // 加入购物车按钮的文字
    addCartText: {
      Type: String,
      default: "加入购物车",
    },
    // 加入购物车按钮的字体颜色
    addCartColor: {
      Type: String,
      default: "#ffffff",
    },
    // 加入购物车按钮的背景颜色
    addCartBackgroundColor: {
      Type: String,
      default: "linear-gradient(to right, $fuint-theme, $fuint-theme)",
    },
    // 不可点击时,按钮的样式
    disableStyle: {
      Type: Object,
      default: null,
    },
    // 按钮点击时的样式
    activedStyle: {
      Type: Object,
      default: null,
    },
    // 按钮常态的样式
    btnStyle: {
      Type: Object,
      default: null,
    },
    // 是否显示右上角关闭按钮
    showClose: {
      Type: Boolean,
      default: true,
    },
    // 关闭按钮的图片地址
    closeImage: {
      Type: String,
      default:
        "https://img.alicdn.com/imgextra/i1/121022687/O1CN01ImN0O11VigqwzpLiK_!!121022687.png",
    },
    // 默认库存数量 (未选择sku时)
    defaultStock: {
      Type: Number,
      default: 0,
    },
    // 默认显示的价格 (未选择sku时)
    defaultPrice: {
      Type: Number,
      default: 0,
    },
  },
  data() {
    return {
      complete: false, // 组件是否加载完成
      goodsInfo: {}, // 商品信息
      isShow: false, // true 显示 false 隐藏
      initKey: true, // 是否已初始化
      shopItemInfo: {}, // 存放要和选中的值进行匹配的数据
      selectArr: [], // 存放被选中的值
      subIndex: [], // 是否选中 因为不确定是多规格还是单规格，所以这里定义数组来判断
      selectShop: {}, // 存放最后选中的商品
      selectNum: this.minBuyNum, // 选中数量
      outFoStock: false, // 是否全部sku都缺货
    };
  },
  mounted() {
    that = this;
    vk = that.vk;
    if (that.value) {
      that.open();
    }
  },
  methods: {
    // 初始化
    init() {
      // 清空之前的数据
      that.selectArr = [];
      that.subIndex = [];
      that.selectShop = {};
      that.selectNum = that.minBuyNum;
      that.outFoStock = false;
      that.shopItemInfo = {};

      let specListName = that.specListName;
      that.goodsInfo[specListName].map((item) => {
        that.selectArr.push("");
        that.subIndex.push(-1);
      });

      that.checkItem(); // 计算sku里面规格形成路径
      that.checkInpath(-1); // 传-1是为了不跳过循环
      that.autoClickSku(); // 自动选择sku策略
    },
    // 使用vk路由模式框架获取商品信息
    findGoodsInfo() {
      if (typeof vk == "undefined") {
        that.toast("custom-action必须是function");
        return false;
      }
      vk.callFunction({
        url: that.action,
        title: "请求中...",
        data: {
          goods_id: that.goodsId,
        },
        success(data) {
          that.updateGoodsInfo(data.goodsInfo);
        },
      });
    },
    // 更新商品信息(库存、名称、图片)
    updateGoodsInfo(goodsInfo) {
      let skuListName = that.skuListName;
      if (
        JSON.stringify(that.goodsInfo) === "{}" ||
        that.goodsInfo[that.goodsIdName] !== goodsInfo[that.goodsIdName]
      ) {
        that.goodsInfo = goodsInfo;
        that.initKey = true;
      } else {
        that.goodsInfo[skuListName] = goodsInfo[skuListName];
      }
      if (that.initKey) {
        that.initKey = false;
        that.init();
      }
      // 更新选中sku的库存信息
      let select_sku_info = that.getListItem(
        that.goodsInfo[skuListName],
        that.skuIdName,
        that.selectShop[that.skuIdName]
      );
      Object.assign(that.selectShop, select_sku_info);
      that.complete = true;
      that.$emit("open", true);
      that.$emit("input", true);
    },
    async open() {
      let findGoodsInfoRun = true;
      let skuListName = that.skuListName;
      if (that.customAction && typeof that.customAction === "function") {
        let goodsInfo = await that.customAction();
        if (
          goodsInfo &&
          typeof goodsInfo == "object" &&
          JSON.stringify(goodsInfo) != "{}"
        ) {
          findGoodsInfoRun = false;
          that.updateGoodsInfo(goodsInfo);
        } else {
          that.toast("无法获取到商品信息");
          that.$emit("input", false);
          return false;
        }
      } else {
        if (findGoodsInfoRun) {
          that.findGoodsInfo();
        }
      }
    },
    // 监听 - 弹出层收起
    close(s) {
      if (s == "close") {
        that.$emit("input", false);
        that.$emit("close", "close");
      } else if (s == "mask") {
        if (that.maskCloseAble) {
          that.$emit("input", false);
          that.$emit("close", "mask");
        }
      }
    },
    moveHandle() {
      //禁止父元素滑动
    },
    // sku按钮的点击事件
    skuClick(value, index1, event, index2) {
      if (value.ishow) {
        if (that.selectArr[index1] != value.name) {
          that.$set(that.selectArr, index1, value.name);
          that.$set(that.subIndex, index1, index2);
        } else {
          that.$set(that.selectArr, index1, "");
          that.$set(that.subIndex, index1, -1);
        }
        that.checkInpath(index1);
        // 如果全部选完
        that.checkSelectShop();
      }
    },
    // 检测是否已经选完sku
    checkSelectShop() {
      // 如果全部选完
      if (that.selectArr.every((item) => item != "")) {
        that.selectShop = that.shopItemInfo[that.selectArr];
        that.selectNum = that.minBuyNum;
      } else {
        that.selectShop = {};
      }
    },
    // 检查路径
    checkInpath(clickIndex) {
      let specListName = that.specListName;
      //循环所有属性判断哪些属性可选
      //当前选中的兄弟节点和已选中属性不需要循环
      let specList = that.goodsInfo[specListName];
      for (let i = 0, len = specList.length; i < len; i++) {
        if (i == clickIndex) {
          continue;
        }
        let len2 = specList[i].list.length;
        for (let j = 0; j < len2; j++) {
          if (that.subIndex[i] != -1 && j == that.subIndex[i]) {
            continue;
          }
          let choosed_copy = [...that.selectArr];
          that.$set(choosed_copy, i, specList[i].list[j].name);
          let choosed_copy2 = choosed_copy.filter(
            (item) => item !== "" && typeof item !== "undefined"
          );
          if (that.shopItemInfo.hasOwnProperty(choosed_copy2)) {
            specList[i].list[j].ishow = true;
          } else {
            specList[i].list[j].ishow = false;
          }
        }
      }
      that.$set(that.goodsInfo, specListName, specList);
    },
    // 计算sku里面规格形成路径
    checkItem() {
      let skuListName = that.skuListName;
      // console.time('计算有多小种可选路径需要的时间是');
      // 去除库存小于等于0的商品sku
      let skuList = that.goodsInfo[skuListName];
      let stockNum = 0;
      for (let i = 0; i < skuList.length; i++) {
        if (skuList[i][that.stockName] <= 0) {
          skuList.splice(i, 1);
          i--;
        } else {
          stockNum += skuList[i][that.stockName];
        }
      }
      if (stockNum <= 0) {
        that.outFoStock = true;
      }
      // 计算有多小种可选路径
      let result = skuList.reduce(
        (arrs, items) => {
          return arrs.concat(
            items[that.skuArrName].reduce(
              (arr, item) => {
                return arr.concat(
                  arr.map((item2) => {
                    // 利用对象属性的唯一性实现二维数组去重
                    if (!that.shopItemInfo.hasOwnProperty([...item2, item])) {
                      that.shopItemInfo[[...item2, item]] = items;
                    }
                    return [...item2, item];
                  })
                );
              },
              [[]]
            )
          );
        },
        [[]]
      );
    },
    // 检测sku选项是否已全部选完,且有库存
    checkSelectComplete(obj = {}) {
      let selectShop = that.selectShop;
      if (selectShop && selectShop[that.skuIdName] !== undefined) {
        // 判断库存
        if (that.selectNum <= selectShop[that.stockName]) {
          if (typeof obj.success == "function") obj.success(selectShop);
        } else {
          that.toast(that.stockText + "不足", "none");
        }
      } else {
        that.toast("请先选择对应规格", "none");
      }
    },
    // 加入购物车
    addCart() {
      that.checkSelectComplete({
        success: function (selectShop) {
          selectShop.buy_num = that.selectNum;
          that.$emit("add-cart", selectShop);
        },
      });
    },
    // 立即购买
    buyNow() {
      that.checkSelectComplete({
        success: function (selectShop) {
          selectShop.buy_num = that.selectNum;
          that.$emit("buy-now", selectShop);
        },
      });
    },
    // 弹窗
    toast(title, icon) {
      uni.showToast({
        title: title,
        icon: icon,
      });
    },
    // 获取对象数组中的某一个item,根据指定的键值
    getListItem(list, key, value) {
      let item;
      for (let i in list) {
        if (typeof value == "object") {
          if (JSON.stringify(list[i][key]) === JSON.stringify(value)) {
            item = list[i];
            break;
          }
        } else {
          if (list[i][key] === value) {
            item = list[i];
            break;
          }
        }
      }
      return item;
    },
    // 自动选择sku前提是只有一组sku,默认自动选择最前面的有库存的sku
    autoClickSku() {
      let skuList = that.goodsInfo[that.skuListName];
      let specListArr = that.goodsInfo[that.specListName];

      if (specListArr.length == 1) {
        let specList = specListArr[0].list;

        for (let i = 0; i < specList.length; i++) {
          let sku = that.getListItem(skuList, that.skuArrName, [
            specList[i].name,
          ]);
          if (sku) {
            that.skuClick(specList[i], 0, {}, i);
            break;
          }
        }
      }
    },
  },
  // 过滤器
  filters: {
    // 金额显示过滤器
    priceFilter(n = 0) {
      if (typeof n == "string") {
        n = parseFloat(n);
      }
      return n ? n.toFixed(2) : n;
    },
  },
  // 计算属性
  computed: {},
  watch: {
    value: function (val) {
      if (val) {
        that.open();
      }
    },
  },
};
</script>

<style lang="scss" scoped>
/*  sku弹出层 */
.goods-sku-popup {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 9999999999;
  overflow: hidden;
  &.show {
    display: block;

    .mask {
      animation: showPopup 0.2s linear both;
    }

    .layer {
      animation: showLayer 0.2s linear both;
    }
  }

  &.hide {
    .mask {
      animation: hidePopup 0.2s linear both;
    }

    .layer {
      animation: hideLayer 0.2s linear both;
    }
  }

  &.none {
    display: none;
  }

  .mask {
    position: fixed;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 1;
    background-color: rgba(0, 0, 0, 0.65);
  }

  .layer {
    display: flex;
    width: 100%;
    max-height: 1200rpx;
    flex-direction: column;
    position: fixed;
    z-index: 999999;
    bottom: 0;
    border-radius: 10rpx 10rpx 0 0;
    background-color: #ffffff;
    margin-top: 10rpx;
    overflow-y: scroll;
    .btn-option {
      padding: 1rpx;
      display: block;
      clear: both;
      margin-bottom: 60rpx;
    }
    .specification-wrapper {
      width: 100%;
      margin-top: 20rpx;
      padding: 30rpx 25rpx;
      box-sizing: border-box;
      .specification-wrapper-content {
        width: 100%;
        min-height: 300rpx;

        &::-webkit-scrollbar {
          /*隐藏滚轮*/
          display: none;
        }

        .specification-header {
          width: 100%;
          display: flex;
          flex-direction: row;
          position: relative;
          margin-bottom: 40rpx;

          .specification-left {
            width: 180rpx;
            height: 180rpx;
            flex: 0 0 180rpx;

            .product-img {
              width: 180rpx;
              height: 180rpx;
              background-color: #999999;
            }
          }

          .specification-right {
            flex: 1;
            padding: 0 35rpx 10rpx 28rpx;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
            justify-content: flex-end;
            font-weight: 500;

            .price-content {
              color: #fe560a;
              margin-bottom: 10rpx;

              .sign {
                font-size: 28rpx;
                margin-right: 4rpx;
              }

              .price {
                font-size: 44rpx;
              }
            }

            .inventory {
              font-size: 24rpx;
              color: #525252;
              margin-bottom: 14rpx;
            }

            .choose {
              font-size: 24rpx;
              color: #525252;
              min-height: 32rpx;
            }
          }
        }

        .specification-content {
          font-weight: 500;
          .specification-item {
            margin-bottom: 40rpx;

            &:last-child {
              margin-bottom: 0;
            }

            .item-title {
              margin-bottom: 15rpx;
              font-size: 32rpx;
              font-weight: bold;
              color: #000000;
            }

            .item-wrapper {
              display: flex;
              flex-direction: row;
              flex-flow: wrap;
              margin-bottom: -20rpx;

              .item-content {
                display: block;
                padding: 10rpx 20rpx;
                min-width: 110rpx;
                text-align: center;
                font-size: 24rpx;
                border-radius: 30rpx;
                background-color: #ffffff;
                color: #333333;
                margin-right: 20rpx;
                margin-bottom: 20rpx;
                border: 2rpx solid #cccccc;
                box-sizing: border-box;

                &.actived {
                  border-color: #fe560a;
                  color: #fe560a;
                }

                &.noactived {
                  // background-color: #e4e4e4;
                  // border-color: #e4e4e4;
                  // color: #9e9e9e;
                  // text-decoration: line-through;
                  color: #c8c9cc;
                  background: #f2f3f5;
                  border-color: #f2f3f5;
                }
              }
            }
          }
        }
      }

      .close {
        position: absolute;
        top: 30rpx;
        right: 25rpx;
        width: 50rpx;
        height: 50rpx;
        text-align: center;
        line-height: 50rpx;

        .close-item {
          width: 40rpx;
          height: 40rpx;
        }
      }
    }

    .btn-wrapper {
      display: flex;
      width: 100%;
      height: 120rpx;
      flex: 0 0 120rpx;
      align-items: center;
      justify-content: space-between;
      padding: 0 26rpx;
      box-sizing: border-box;

      .layer-btn {
        width: 335rpx;
        height: 80rpx;
        border-radius: 40rpx;
        color: #fff;
        line-height: 80rpx;
        text-align: center;
        font-weight: 500;
        font-size: 28rpx;

        &.add-cart {
          background: #ffbe46;
        }

        &.buy {
          background: #fe560a;
        }
      }

      .sure {
        width: 698rpx;
        height: 80rpx;
        border-radius: 38rpx;
        color: #fff;
        line-height: 80rpx;
        text-align: center;
        font-weight: 500;
        font-size: 28rpx;
        background: #fe560a;
      }

      .sure.add-cart {
        background: $fuint-theme;
      }
    }
  }

  @keyframes showPopup {
    0% {
      opacity: 0;
    }

    100% {
      opacity: 1;
    }
  }

  @keyframes hidePopup {
    0% {
      opacity: 1;
    }

    100% {
      opacity: 0;
    }
  }

  @keyframes showLayer {
    0% {
      transform: translateY(120%);
    }

    100% {
      transform: translateY(0%);
    }
  }

  @keyframes hideLayer {
    0% {
      transform: translateY(0);
    }

    100% {
      transform: translateY(120%);
    }
  }
}
</style>
